package com.dly.blog.provider;

import cn.hutool.core.thread.lock.LockUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dly.blog.content.RedisContent;
import com.dly.blog.domain.User;
import com.dly.blog.domain.UserRole;
import com.dly.blog.mapper.RoleMapper;
import com.dly.blog.mapper.UserMapper;
import com.dly.blog.mapper.UserRoleMapper;
import com.dly.blog.provider.user.UserProvider;
import com.dly.blog.utile.SecurityUtils;
import lombok.AllArgsConstructor;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Author: DaiLiYu
 * @Date: 2023/7/12 23:24
 */
@Component
@AllArgsConstructor
public class UserProviderImpl implements UserProvider {

    private UserMapper userMapper;

    private UserRoleMapper userRoleMapper;

    private RedissonClient redissonClient;

    @Override
    public User selectByUserAccount(String userAccount) {
        return userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUserAccount, userAccount));
    }

    @Override
    public User selectByEmail(String email) {
        return userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUserEmail, email));
    }

    @Override
    public User selectById(String id) {
        return userMapper.selectById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insert(User user) {
        int insert = userMapper.insert(user);
        if(insert > 0){
            //赋予用户角色
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId("2");
            userRoleMapper.insert(userRole);
        }
    }

    @Override
    public void updatePassword(User user) {
        userMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reducedFrequency(String userId, int frequency) {
        RLock lock = redissonClient.getLock(RedisContent.LOCK + userId);
        try {
            if (lock.tryLock(2, TimeUnit.MINUTES)) {
                userMapper.update(null, new UpdateWrapper<User>().lambda()
                        .eq(User::getId, userId)
                        .setSql("frequency = frequency - " + frequency)
                );
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addFrequency(String userId, int frequency) {
        RLock lock = redissonClient.getLock(RedisContent.LOCK + userId);
        try {
            if (lock.tryLock(2, TimeUnit.MINUTES)) {
                userMapper.update(null, new UpdateWrapper<User>().lambda()
                        .eq(User::getId, userId)
                        .setSql("frequency = frequency + " + frequency)
                );
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public Boolean chickFrequency(int frequency) {
        User user = userMapper.selectById(SecurityUtils.getUserId());
        return user.getFrequency() - frequency >= 0;
    }

    @Override
    public Integer getFrequency() {
        User user = userMapper.selectById(SecurityUtils.getUserId());
        return user.getFrequency();
    }

    @Override
    public void bindWX(String userId, String openId) {
        userMapper.setOpenId(userId, openId);
    }

    @Override
    public User selectByOpenId(String openId) {
       return  userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenId, openId));
    }
}
